package com.vision.admin.company.cl.ui;

import static com.vision.admin.cl.AdminServices.companyGroupSvc;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.SimpleBeanEditorDriver;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiFactory;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.core.client.Style.SelectionMode;
import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.widget.core.client.TabItemConfig;
import com.sencha.gxt.widget.core.client.Window;
import com.sencha.gxt.widget.core.client.button.TextButton;
import com.sencha.gxt.widget.core.client.container.AbstractHtmlLayoutContainer.HtmlData;
import com.sencha.gxt.widget.core.client.container.HtmlLayoutContainer;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer;
import com.sencha.gxt.widget.core.client.event.HideEvent;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.form.TextArea;
import com.sencha.gxt.widget.core.client.form.TextField;
import com.sencha.gxt.widget.core.client.grid.ColumnConfig;
import com.sencha.gxt.widget.core.client.grid.ColumnModel;
import com.sencha.gxt.widget.core.client.grid.Grid;
import com.sencha.gxt.widget.core.client.grid.GridView;
import com.sencha.gxt.widget.core.client.selection.SelectionChangedEvent;
import com.sencha.gxt.widget.core.client.selection.SelectionChangedEvent.SelectionChangedHandler;
import com.vision.admin.cl.AdminTasks;
import com.vision.admin.cl.resource.AdminResources;
import com.vision.admin.cl.ui.AbstractView;
import com.vision.core.cl.BaseModule;
import com.vision.core.cl.Callback;
import com.vision.core.cl.event.CompanyCreatedEvent;
import com.vision.core.cl.event.CompanyGroupCreatedEvent;
import com.vision.core.cl.event.CreatedEvent;
import com.vision.core.cl.event.CreatedEvent.CreationHandler;
import com.vision.core.cl.mvp.Presenter;
import com.vision.core.cl.ui.ConfirmDialogHandler;
import com.vision.core.cl.ui.UI;
import com.vision.core.cl.ui.component.BasicGridView;
import com.vision.core.cl.util.FieldUtils;
import com.vision.core.cm.data.CompanyGroupProperties;
import com.vision.core.cm.data.CompanyProperties;
import com.vision.core.cm.db.data.Company;
import com.vision.core.cm.db.data.CompanyGroup;

/**
 * 
 * @author Mark
 *
 */
public class CompaniesPanel extends AbstractView<Company> {
	
	interface CompanyBinder extends UiBinder<Widget, CompaniesPanel> {}
	interface CompanyDriver extends SimpleBeanEditorDriver<Company, CompaniesPanel> {} 
	
	@UiField VerticalLayoutContainer mainPanel;

	@Ignore @UiField TextButton refreshBtn;
	@Ignore @UiField TextButton addBtn;
	@Ignore @UiField TextButton deleteBtn;
	
	@UiField Grid<Company> grid;
	
	@UiField HtmlLayoutContainer formContainer;
	
	@UiField TextField code;
	@UiField TextField name;
	@UiField TextArea address;
	@UiField TextField phone;
	@UiField TextField fax;
	
	@Ignore @UiField TextButton saveBtn;
	@Ignore @UiField TextButton cancelBtn;
	
	@Ignore @UiField TextButton addGroupBtn;
	@Ignore @UiField TextButton deleteGroupBtn;
	
	@UiField(provided = true) Grid<CompanyGroup> companyGroupsGrid;
	
	private Company currentCompany = null;
	
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	public CompaniesPanel() {
		super(GWT.<CompanyBinder>create(CompanyBinder.class),
				GWT.<CompanyDriver>create(CompanyDriver.class));
		
		Presenter<Company> presenter = new CompaniesPresenter();
		setPresenter(presenter);
		presenter.setView(this);
		
		// Global Handlers -- should be registered only once
		BaseModule.addHandler(CompanyCreatedEvent.TYPE, new CreationHandler<Company>() {
			@Override
			public void onCreated(CreatedEvent<Company> e) {
				grid.getStore().add(e.getObject());
			}
		});

		// Global Handlers -- should be registered only once
		BaseModule.addHandler(CompanyGroupCreatedEvent.TYPE, new CreationHandler<CompanyGroup>() {
			@Override
			public void onCreated(CreatedEvent<CompanyGroup> e) {
				loadGroups(((CompanyGroup) e.getObject()).getCompany());	
			}
		});
		
		// Add validators to fields
		FieldUtils.minMaxOf(code, 1, Company.FieldSpecs.CODE_MAX);
		FieldUtils.minMaxOf(name, 1, Company.FieldSpecs.NAME_MAX);
		FieldUtils.maxOf(address, Company.FieldSpecs.ADDRESS_MAX);
		FieldUtils.maxOf(phone, Company.FieldSpecs.PHONE_MAX);
		FieldUtils.maxOf(fax, Company.FieldSpecs.FAX_MAX);
	}
	
	@Override
	protected void preBinderInvoke() {
		companyGroupsGrid = initializeCompanyGroupsGrid();
	}
	
	@Override
	protected Grid<Company> getGrid() {
		return grid;
	}
	
	// UiFactory Methods %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%	
	
	@UiFactory
	Grid<Company> initializeGrid() {
		CompanyProperties props = CompanyProperties.INSTANCE;

		List<ColumnConfig<Company, ?>> columns = new ArrayList<ColumnConfig<Company, ?>>();

		columns.add(UI.column(props.code(), 80, "Code"));
		columns.add(UI.column(props.name(), 300, "Name"));
		
		ColumnConfig<Company, String> address = UI.column(props.address(), 420, "Address");
		columns.add(address);

		ColumnModel<Company> cm = new ColumnModel<Company>(columns);

		final Grid<Company> grid = new Grid<Company>(new ListStore<Company>(props.key()), cm);
		grid.setAllowTextSelection(false);
		grid.setHeight(150);
		grid.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
		
		GridView<Company> view = new BasicGridView<Company>();
		view.setAutoExpandColumn(address);
		view.setEmptyText("There are no companies to display.");
		grid.setView(view);
		
		// Add a listener to the grid
		grid.getSelectionModel().addSelectionChangedHandler(new SelectionChangedHandler<Company>() {
			@Override
			public void onSelectionChanged(SelectionChangedEvent<Company> event) {
				presenter.onSelect(getSelected());
			}
		});
		
		return grid;
	}
	
	Grid<CompanyGroup> initializeCompanyGroupsGrid() {
		CompanyGroupProperties props = CompanyGroupProperties.INSTANCE;
		
		List<ColumnConfig<CompanyGroup, ?>> columns = new ArrayList<ColumnConfig<CompanyGroup, ?>>();
		
		ColumnConfig<CompanyGroup, String> codeColumn = UI.column(props.code(), 200, "Code");
		ColumnConfig<CompanyGroup, String> descColumn = UI.column(props.description(), 400, "Description");
		columns.add(codeColumn);		
		columns.add(descColumn);
		
		ListStore<CompanyGroup> store = new ListStore<CompanyGroup>(props.key());
		
		GridView<CompanyGroup> view = new BasicGridView<CompanyGroup>();
		view.setAutoExpandColumn(descColumn);
		view.setEmptyText("There are no company groups to display.");
		
		Grid<CompanyGroup> grid = new Grid<CompanyGroup>(store, new ColumnModel<CompanyGroup>(columns), view);
		
		return grid;
	}
	
	@UiFactory
	HtmlLayoutContainer initializeFormContainer() {
		return new HtmlLayoutContainer(getFormLayout());
	}
	
	@UiFactory
	HtmlData createHtmlData() {
		return new HtmlData("");
	}
	
	// UiHandler Methods %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	@UiHandler("refreshBtn")
	void refreshClicked(SelectEvent e) {
		presenter.onRefreshClicked(e);
	}
	
	@UiHandler("addBtn")
	void addClicked(SelectEvent e) {
		presenter.onAddClicked(e);
	}

	@UiHandler("deleteBtn")
	void deleteClicked(SelectEvent e) {
		presenter.onDeleteClicked(e);
	}
	
	@UiHandler("saveBtn")
	void saveClicked(SelectEvent e) {
		presenter.onSaveClicked(e);
	}
	
	@UiHandler("cancelBtn")
	void cancelClicked(SelectEvent e) {
		presenter.onCancelClicked(e);
	}
	
	@UiHandler("addGroupBtn")
	void addGroupClicked(SelectEvent e) {
		if (currentCompany == null)
			return;
		
		Window w = (Window) new CreateCompanyGroupWindow(currentCompany).asWidget();
		w.show();
	}
	
	@UiHandler("deleteGroupBtn")
	void deleteGroupClicked(SelectEvent e) {
		final CompanyGroup selected = companyGroupsGrid.getSelectionModel().getSelectedItem();
		if (selected == null)
			return;

		UI.confirm("Confirm Delete", "Are you sure you want to delete '" + selected.getCode() + "'?",
			new ConfirmDialogHandler() {
				@Override
				public void onYes(HideEvent event) {
					UI.mask(mainPanel, "Deleting " + selected.getCode() + "...");
					companyGroupSvc().delete(selected, new Callback<CompanyGroup>(mainPanel) {
						@Override
						protected void handleSuccess(CompanyGroup result) {
							companyGroupsGrid.getStore().remove(result);
							//BaseModule.fireEvent(new CompanyGroupDeletedEvent(result));
						}
					});
				}
			}
		);
	}
	
	
	// Logic %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	public void edit(final Company company) {
		currentCompany = company;
		
		driver.edit(company);
		
		saveBtn.setEnabled(company != null);
		cancelBtn.setEnabled(company != null);
		
		if (company == null)
			return;
		
		loadGroups(company);
	}
	
	private void loadGroups(Company company) {
		companyGroupsGrid.mask("Loading...");
		companyGroupSvc().getGroups(company, new Callback<List<CompanyGroup>>(companyGroupsGrid) {
			@Override
			protected void handleSuccess(List<CompanyGroup> result) {
				companyGroupsGrid.getStore().clear();
				companyGroupsGrid.getStore().addAll(result);
			}
		});
	}

	// ITabItemPanel Methods %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	@Override
	public String getPanelId() {
		return AdminTasks.COMPANIES.getId();
	}
	
	@Override
	public TabItemConfig getConfig() {
		return getConfig("Companies", true, AdminResources.INSTANCE.companies());
	}

	// Helper Methods %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	private static native String getFormLayout() /*-{
	    return [ 
	    '<table width=100% cellpadding=0 cellspacing=0>',
		    '<tr><td class=code width=50%></td><td class=name width=50%></td></tr>',
		    '<tr><td class=phone width=50%></td><td class=fax width=50%></td></tr>',
		    '<tr><td class=address colspan=2></td></tr>',
	    '</table>'
		].join("");
	}-*/;

}
